﻿using ProtoBuf;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Fetion.Core
{
    public class PackageModel:IMessage
    {

        #region 包头
        private int packageLength;
        /// <summary>
        /// 包长，包括消息头和消息体长度
        /// </summary>
        public int PackageLength
        {
            get { return packageLength; }
            set { packageLength = value; }
        }
        private byte version=30;
        /// <summary>
        /// 协议版本号：目前是MCP3.0
        /// </summary>
        public byte Version
        {
            get { return version; }
            set { version = value; }
        }
        private int userId;
        /// <summary>
        /// 用户id
        /// </summary>
        public int UserId
        {
            get { return userId; }
            set { userId = value; }
        }
        private int cmd;
        /// <summary>
        /// 请求命令字
        /// </summary>
        public int CMD
        {
            get { return cmd; }
            set { cmd = value; }
        }
        private Int16 seq;
        /// <summary>
        /// 请求ID  范围：1~32767
        /// </summary>
        public Int16 Seq
        {
            get { return seq; }
            set { seq = value; }
        }
        private static Int16 curId;
        public static Int16 GetSeq()
        {
            if (curId >= Int16.MaxValue)
            {
                curId = 0;
                return ++curId;
            }
            else
            {
                return ++curId;
            }
        }
        private int offset;
        /// <summary>
        /// 包头的偏移量，包括OPT的消息头总长度
        /// </summary>
        public int Offset
        {
            get { return offset; }
            set { offset = value; }
        }
        private byte format=0x0;
        /// <summary>
        /// 标志位: 0x80为应答,0x00为请求
        /// </summary>
        public byte Format
        {
            get { return format; }
            set { format = value; }
        }

        private byte flagEncrypted;
        /// <summary>
        /// 加密/压缩标志. 0x1:压缩标志; 0x2:加密标志
        /// </summary>
        public byte FlagEncrypted
        {
            get { return flagEncrypted; }
            set { flagEncrypted = value; }
        }
        private Int16 clientType=36;//winphone
        /// <summary>
        /// 客户端类型
        /// </summary>
        public Int16 ClientType
        {
            get { return clientType; }
            set { clientType = value; }
        }
        private Int16 clientVersion;
        /// <summary>
        /// 客户端版本号
        /// </summary>
        public Int16 ClientVersion
        {
            get { return clientVersion; }
            set { clientVersion = value; }
        }
        private byte[] opt;
        /// <summary>
        /// 可扩展包头, 默认预留4个字节
        /// </summary>
        public byte[] Opt
        {
            get { return opt; }
            set { opt = value; }
        }
        #endregion

        #region 包体
        public void SetBody<T>(T t)
        {
            bodyModel = t;
        }
        private object bodyModel;

        public object BodyModel
        {
            get { return bodyModel; }
            set { bodyModel = value; }
        }

        private byte[] body;
        /// <summary>
        /// 包体
        /// </summary>
        public byte[] Body
        {
            get { return body; }
            set { body = value; }
        }
        #endregion

        public PackageModel()
        { 

        }
        public PackageModel(int userId, int cmd, short seq, byte format, byte flagEncrypted, Int16 clientType, Int16 clientVersion, byte[] body)
        {
            this.UserId = userId;
            this.CMD = cmd;
            this.Seq = seq;
            this.Format = format;
            this.FlagEncrypted = flagEncrypted;
            this.ClientType = clientType;
            this.ClientVersion = clientVersion;
            this.Body = body;
        }
        public PackageModel(int userId,int cmd,byte[] body)
        :this(userId,cmd,GetSeq(),0,0,36,1,body)
        {
            
        }

        /// <summary>
        /// header默认长度
        /// </summary>
        private const int defaultHeadLength = 25;
        /// <summary>
        /// 返回包的流
        /// </summary>
        /// <returns></returns>
        public byte[] GetBuffer()
        {
            if (Body.Length == 0)
            {
                throw new Exception("包体长度不能为空");
            }
            int length = defaultHeadLength + body.Length;
            MemoryStream ms = new MemoryStream(length);
            //组合header     
            //int length = 25 + pb.body.Length;
            byte[] hLength = BitConverter.GetBytes(length);
            ms.Write(hLength, 0, 2);
            //byte[] hVersion = System.Text.Encoding.UTF8.GetBytes("2.5");
            byte[] hVersion = new byte[1];//BitConvertHelper.getBytes(30);
            hVersion[0] = version;
            ms.Write(hVersion, 0, 1);
            byte[] hUserId = BitConverter.GetBytes(userId);
            ms.Write(hUserId, 0, 4);
            byte[] hCMD = BitConverter.GetBytes(cmd);//10102
            ms.Write(hCMD, 0, 4);
            byte[] hSeq = BitConverter.GetBytes(seq);
            ms.Write(hSeq, 0, 2);
            byte[] hOffset = BitConverter.GetBytes(defaultHeadLength);
            ms.Write(hOffset, 0, 1);
            byte[] hFormat = BitConverter.GetBytes(format);
            ms.Write(hFormat, 0, 1);
            byte[] hFlag = BitConverter.GetBytes(flagEncrypted);
            ms.Write(hFlag, 0, 1);
            byte[] hClientType = BitConverter.GetBytes(clientType);//36
            ms.Write(hClientType, 0, 2);
            byte[] hClientVersion = BitConverter.GetBytes(clientVersion);//1
            ms.Write(hClientVersion, 0, 2);
            //空位
            byte[] hBlankBit = new byte[1];

            ms.Write(hBlankBit, 0, 1);
            byte[] hOption = new byte[4];
            ms.Write(hOption, 0, 4);
            //组合header 结束
            //组合body
            //using (MemoryStream bodyMs = new MemoryStream())
            //{
            //    Serializer.Serialize<T>(bodyMs, bodyModel);
            //    body = bodyMs.GetBuffer();
            //}
            ms.Write(body, 0, body.Length);
            //组合body 结束
            return ms.GetBuffer();
        }

        public void Save(BufferWriter writer)
        {
            throw new NotImplementedException();
        }

        public void Load(BufferReader reader)
        {
            throw new NotImplementedException();
        }
    }
}
